home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / time.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  21KB  |  790 lines

  1. /*
  2.  * static char *rcsid_time_c =
  3.  *    "$Id: time.c,v 1.30 1996/01/02 11:53:56 master Exp $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1994 Mark Wedel
  10.     Copyright (C) 1992 Frank Tore Johansen
  11.  
  12.     This program is free software; you can redistribute it and/or modify
  13.     it under the terms of the GNU General Public License as published by
  14.     the Free Software Foundation; either version 2 of the License, or
  15.     (at your option) any later version.
  16.  
  17.     This program is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.     GNU General Public License for more details.
  21.  
  22.     You should have received a copy of the GNU General Public License
  23.     along with this program; if not, write to the Free Software
  24.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  
  26.     The author can be reached via e-mail to master@rahul.net
  27. */
  28.  
  29. /*
  30.  * Routines that is executed from objects based on their speed have been
  31.  * collected in this file.
  32.  */
  33.  
  34. #include <global.h>
  35. #include <spells.h>
  36. #ifndef __CEXTRACT__
  37. #include <sproto.h>
  38. #endif
  39.  
  40. /* The following removes doors.  The functions check to see if similar 
  41.  * doors are next to the one that is being removed, and if so, set it
  42.  * so those will be removed shortly (in a cascade like fashion.)
  43.  */
  44.  
  45. void remove_door(object *op) {
  46.   int i;
  47.   object *tmp;
  48.   for(i=1;i<9;i+=2)
  49.     if((tmp=present(DOOR,op->map,op->x+freearr_x[i],op->y+freearr_y[i]))!=NULL) {
  50.       tmp->speed = 0.1;
  51.       update_ob_speed(tmp);
  52.       tmp->speed_left= -0.2;
  53.     }
  54.   remove_ob(op);
  55.   free_object(op);
  56. }
  57.  
  58. void remove_door2(object *op) {
  59.   int i;
  60.   object *tmp;
  61.   for(i=1;i<9;i+=2) {
  62.     tmp=present(LOCKED_DOOR,op->map,op->x+freearr_x[i],op->y+freearr_y[i]);
  63.     if(tmp && tmp->slaying == op->slaying) {/* same key both doors */
  64.       tmp->speed = 0.1;
  65.       update_ob_speed(tmp);
  66.       tmp->speed_left= -0.2;
  67.     }
  68.   }
  69.   remove_ob(op);
  70.   free_object(op);
  71. }
  72.  
  73. void generate_monster(object *gen) {
  74.   int i;
  75.   object *op,*head=NULL,*prev=NULL;
  76.   archetype *at=gen->other_arch;
  77.  
  78.   if(GENERATE_SPEED(gen)&&RANDOM()%GENERATE_SPEED(gen))
  79.     return;
  80.   if(gen->other_arch==NULL) {
  81.     LOG(llevError,"Generator without other_arch: %s\n",gen->name);
  82.     return;
  83.   }
  84.   i=find_free_spot(at,gen->map,gen->x,gen->y,1,9);
  85.   if(!i) return;
  86.   while(at!=NULL) {
  87.     op=arch_to_object(at);
  88.     op->x=gen->x+freearr_x[i]+at->clone.x;
  89.     op->y=gen->y+freearr_y[i]+at->clone.y;
  90.     if(head!=NULL)
  91.       op->head=head,prev->more=op;
  92.     insert_ob_in_map(op,gen->map);
  93.     if (QUERY_FLAG(op, FLAG_FREED)) return;
  94.     if(op->arch->randomitems!=NULL)
  95.       create_treasure(op->arch->randomitems,op,GT_INVENTORY,
  96.                       gen->map->difficulty,0);
  97.     if(head==NULL)
  98.       head=op;
  99.     prev=op;
  100.     at=at->more;
  101.   }
  102.   if(gen->stats.food&&!--(gen->stats.food)) {
  103.     remove_ob(gen);
  104.     free_object(gen);
  105.   }
  106. }
  107.  
  108. void regenerate_rod(object *rod) {
  109.   if(++rod->stats.food > rod->stats.hp/10 || rod->type == HORN) {
  110.     rod->stats.food = 0;
  111.     if (rod->stats.hp < rod->stats.maxhp) {
  112.       rod->stats.hp += 1 + rod->stats.maxhp/10;
  113.       if (rod->stats.hp > rod->stats.maxhp)
  114.         rod->stats.hp = rod->stats.maxhp;
  115.       fix_rod_speed(rod);
  116.     }
  117.   }
  118. }
  119.  
  120. void remove_force(object *op) {
  121.   if(op->env==NULL) {
  122.     remove_ob(op);
  123.     free_object(op);
  124.     return;
  125.   }
  126.   CLEAR_FLAG(op, FLAG_APPLIED);
  127.   change_abil(op->env,op);
  128.   fix_player(op->env);
  129.   remove_ob(op);
  130.   free_object(op);
  131. }
  132.  
  133. void remove_blindness(object *op) {
  134.   if(--op->stats.food > 0)
  135.     return;
  136.   CLEAR_FLAG(op, FLAG_APPLIED);
  137.   if(op->env!=NULL) { 
  138.      change_abil(op->env,op);
  139.      fix_player(op->env);
  140.   }
  141.   remove_ob(op);
  142.   free_object(op);
  143. }
  144.  
  145. void remove_confusion(object *op) {
  146.   if(--op->stats.food > 0)
  147.     return;
  148.   if(op->env!=NULL) {
  149.     CLEAR_FLAG(op->env, FLAG_CONFUSED);
  150.     new_draw_info(NDI_UNIQUE, 0,op->env, "You regain your senses.\n");
  151.   }
  152.   remove_ob(op);
  153.   free_object(op);
  154. }
  155.  
  156. void execute_wor(object *op) {
  157.   object *wor=op;
  158.   while(op!=NULL&&op->type!=PLAYER)
  159.     op=op->env;
  160.   if(op!=NULL) {
  161.     if(blocks_magic(op->map,op->x,op->y))
  162.       new_draw_info(NDI_UNIQUE, 0,op,"You feel something fizzle inside you.");
  163.     else
  164.       enter_exit(op,wor);
  165.   }
  166.   remove_ob(wor);
  167.   free_object(wor);
  168. }
  169.  
  170. void poison_more(object *op) {
  171.   if(op->env==NULL||!QUERY_FLAG(op->env,FLAG_ALIVE)||op->env->stats.hp<0) {
  172.     remove_ob(op);
  173.     free_object(op);
  174.     return;
  175.   }
  176.   if(op->stats.food==1) {
  177.     /* need to remove the object before fix_player is called, else fix_player
  178.      * will not do anything.
  179.      */
  180.     if(op->env->type==PLAYER) {
  181.       CLEAR_FLAG(op, FLAG_APPLIED);
  182.       fix_player(op->env);
  183.       new_draw_info(NDI_UNIQUE, 0,op->env,"You feel much better now.");
  184.     }
  185.     remove_ob(op);
  186.     free_object(op);
  187.     return;
  188.   }
  189.   if(op->env->type==PLAYER) {
  190.     op->env->stats.food--;
  191.     new_draw_info(NDI_UNIQUE, 0,op->env,"You feel very sick...");
  192.     draw_stats(op->env);
  193.   }
  194.   (void)hit_player(op->env,
  195.                    op->stats.dam,
  196.                    op,AT_PHYSICAL);
  197. }
  198.  
  199.  
  200. void move_gate(object *op) { /* 1 = going down, 0 = goind up */
  201.   object *tmp;
  202.   if(op->stats.wc < 0 || (int)op->stats.wc  > (int)op->arch->animations-1) {
  203.     LOG(llevError,"Gate error: animation was %d\n",op->stats.wc);
  204.     dump_object(op);
  205.     LOG(llevError,"%s\n",errmsg);
  206.     op->stats.wc=0;
  207.   }
  208.   if(op->value) { /* We're going down */
  209.     if(--op->stats.wc<=0) { /* Reached bottom, let's stop */
  210.       op->stats.wc=0;
  211.       if(op->arch->clone.speed)
  212.         op->value=0;
  213.       else {
  214.     op->speed = 0;
  215.     update_ob_speed(op);
  216.       }
  217.       CLEAR_FLAG(op, FLAG_NO_PASS);
  218.       CLEAR_FLAG(op, FLAG_BLOCKSVIEW);
  219.       update_all_los(op->map);
  220.     }
  221.     if((int)op->stats.wc <= ((int)op->arch->animations-1)/2+1) {
  222.       CLEAR_FLAG(op, FLAG_NO_PASS);
  223.       CLEAR_FLAG(op, FLAG_BLOCKSVIEW);
  224.       update_all_los(op->map);
  225.     }
  226.     op->face=&new_faces[op->arch->faces[op->stats.wc]];
  227.     update_object(op);
  228.     return;
  229.   }
  230.   /* We're going up */
  231.   if((unsigned char) op->stats.wc==(op->arch->animations-1)&&op->above==NULL) {
  232.     if(op->arch->clone.speed)
  233.       op->value=1;
  234.     else {
  235.     op->speed = 0;
  236.     update_ob_speed(op); /* Reached top, let's stop */
  237.     }
  238.     return;
  239.   }
  240.   if(op->stats.food) {    /* The gate is going temporarily down */
  241.     if(--op->stats.wc<=0) /* Gone all the way down? */
  242.       op->stats.food=0,   /* Then let's try again */
  243.       op->stats.wc=0;
  244.   } else {                /* The gate is still going up */
  245.     op->stats.wc++;
  246.     if((int)op->stats.wc > ((int)op->arch->animations-1))
  247.       op->stats.wc=(signed char)op->arch->animations-1;
  248.     if((int)op->stats.wc >= (int)op->arch->animations/2) {
  249.       /* Halfway or further, check blocks */
  250.       for(tmp=op->above;tmp!=NULL&&tmp->above!=NULL;tmp=tmp->above); /* top */
  251.       if(tmp!=NULL) {
  252.         if(QUERY_FLAG(tmp, FLAG_ALIVE)) {
  253.           hit_player(tmp,RANDOM()%(op->stats.dam+1)+1,op,AT_PHYSICAL);
  254.           if(tmp->type==PLAYER) {
  255.         new_draw_info_format(NDI_UNIQUE, 0, tmp,
  256.         "You are crushed by the %s!",op->name);
  257.           }
  258.         } else if(!(tmp->speed&&tmp->direction)) {
  259.           /* If it has speed, it should move itself, otherwise: */
  260.           int i=find_free_spot(tmp->arch,op->map,op->x,op->y,1,9);
  261.           remove_ob(tmp);
  262.           tmp->x+=freearr_x[i],tmp->y+=freearr_y[i];
  263.           insert_ob_in_map(tmp,op->map);
  264.         }
  265.       }
  266.       if(op->above!=NULL)   /* Still something in the way? */
  267.         op->stats.food=1;   /* Then let's go down and gather some speed 8) */
  268.       else {
  269.         SET_FLAG(op, FLAG_NO_PASS);    /* The coast is clear, block the way */
  270.         if(!op->arch->clone.stats.ac)
  271.           SET_FLAG(op, FLAG_BLOCKSVIEW);
  272.         update_all_los(op->map);
  273.       }
  274.     }
  275.   }
  276.   op->face=&new_faces[op->arch->faces[(unsigned char)op->stats.wc]];
  277.   update_object(op);
  278. }
  279.  
  280. /*  hp      : how long door is open/closed
  281.  *  maxhp   : initial value for hp
  282.  *  sp      : 1 = open, 0 = close
  283.  */
  284. void move_timed_gate(object *op)
  285. {
  286.   int v = op->value;
  287.  
  288.   if (op->stats.sp) {
  289.     move_gate(op);
  290.     if (op->value != v)   /* change direction ? */
  291.       op->stats.sp = 0;
  292.     return;
  293.   } 
  294.   if (--op->stats.hp <= 0) { /* keep gate down */
  295.     move_gate(op);
  296.     if (op->value != v) {  /* ready ? */
  297.     op->speed = 0;
  298.     update_ob_speed(op);
  299.     }
  300.   }
  301. }
  302.  
  303. void animate_trigger (object *op)
  304. {
  305.   if((unsigned char)++op->stats.wc >= op->arch->animations-1) {
  306.     op->stats.wc = 0;
  307.     check_trigger(op);
  308.   }
  309.   op->face=&new_faces[op->arch->faces[op->stats.wc]];
  310.   update_object(op);
  311. }
  312.  
  313. void move_hole(object *op) { /* 1 = opening, 0 = closing */
  314.   if(op->value) { /* We're opening */
  315.     if(--op->stats.wc<=0) { /* Opened, let's stop */
  316.       op->stats.wc=0;
  317.       op->speed = 0;
  318.       update_ob_speed(op);
  319.       SET_FLAG(op, FLAG_WALK_ON);
  320.       while(op->above!=NULL && apply(op->above,op))
  321.         ;
  322.     }
  323.     op->face=&new_faces[op->arch->faces[op->stats.wc]];
  324.     update_object(op);
  325.     return;
  326.   }
  327.   /* We're closing */
  328.   CLEAR_FLAG(op, FLAG_WALK_ON);
  329.   op->stats.wc++;
  330.   if((int)op->stats.wc > (int)op->arch->animations-1)
  331.     op->stats.wc=op->arch->animations-1;
  332.   op->face=&new_faces[op->arch->faces[op->stats.wc]];
  333.   update_object(op);
  334.   if((unsigned char) op->stats.wc==op->arch->animations-1) {
  335.     op->speed = 0;
  336.     update_ob_speed(op); /* closed, let's stop */
  337.     return;
  338.   }
  339. }
  340.  
  341.  
  342. void stop_arrow(object *op,object *tmp) {
  343.   if(wall(op->map,op->x,op->y))
  344.     op->x-=DIRX(op),op->y-=DIRY(op);
  345.   if(wall(op->map, op->x, op->y))
  346.   {
  347.     free_object(op);
  348.     return;
  349.   }
  350.   if(RANDOM() % 100 < op->stats.food) {
  351.     /* Small chance of breaking */
  352.     free_object(op);
  353.     return;
  354.   }
  355.   op->direction=0;
  356.   CLEAR_FLAG(op, FLAG_WALK_ON);
  357.   CLEAR_FLAG(op, FLAG_FLY_ON);
  358.   CLEAR_FLAG(op, FLAG_FLYING);
  359.   op->speed = 0;
  360.   update_ob_speed(op);
  361.   op->stats.wc = op->stats.sp;
  362.   op->stats.dam= op->stats.hp;
  363.   /* Reset these to zero, so that CAN_MERGE will work properly */
  364.   op->stats.sp = 0;
  365.   op->stats.hp = 0;
  366.   op->face=op->arch->clone.face;
  367.   if(tmp!=NULL&&tmp->stats.hp>=0) {
  368.     if(tmp->head != NULL)
  369.       tmp = tmp->head;
  370.     op = insert_ob_in_ob(op,tmp);
  371.     if (tmp->type== PLAYER && tmp->contr->eric_server > 0)
  372.       esrv_send_item (tmp, op);
  373.   } else
  374.     insert_ob_in_map(op,op->map);
  375.   op->owner=NULL; /* So that stopped arrows will be saved */
  376. }
  377.  
  378. void move_arrow(object *op) {
  379.   object *tmp;
  380.  
  381.   if(op->map==NULL) {
  382.     LOG(llevError,"Arrow had no map.\n");
  383.     remove_ob(op);
  384.     free_object(op);
  385.     return;
  386.   }
  387.   remove_ob(op);
  388.   if(wall(op->map,op->x+DIRX(op),op->y+DIRY(op)))
  389.     if(!QUERY_FLAG(op, FLAG_REFLECTING) || !(RANDOM()%20)) {
  390.       stop_arrow(op,NULL);
  391.       return;
  392.     } else {
  393.       if(op->direction&1)
  394.     op->direction=absdir(op->direction+4);
  395.       else {
  396.         int left= wall(op->map,op->x+freearr_x[absdir(op->direction-1)],
  397.                op->y+freearr_y[absdir(op->direction-1)]),
  398.     right=wall(op->map,op->x+freearr_x[absdir(op->direction+1)],
  399.            op->y+freearr_y[absdir(op->direction+1)]);
  400.         if(left==right)
  401.           op->direction=absdir(op->direction+4);
  402.         else if(left)
  403.           op->direction=absdir(op->direction+2);
  404.         else if(right)
  405.           op->direction=absdir(op->direction-2);
  406.       }
  407.       if(wall(op->map,op->x+DIRX(op),op->y+DIRY(op)))
  408.     {
  409.       int left= wall(op->map,op->x+freearr_x[absdir(op->direction-1)],
  410.              op->y+freearr_y[absdir(op->direction-1)]),
  411.       right=wall(op->map,op->x+freearr_x[absdir(op->direction+1)],
  412.              op->y+freearr_y[absdir(op->direction+1)]);
  413.       if(!left)
  414.         op->direction=absdir(op->direction-1);
  415.       else if(!right)
  416.         op->direction=absdir(op->direction+1);
  417.       else {        /* is this possible? */
  418.         stop_arrow(op,NULL);
  419.         return;
  420.       }
  421.     }
  422.       op->face=&new_faces[op->arch->faces[op->direction]];
  423.   }
  424.   op->x+=DIRX(op),op->y+=DIRY(op);
  425.   tmp=get_map_ob(op->map,op->x,op->y);
  426.   while(tmp!=NULL&&!QUERY_FLAG(tmp, FLAG_ALIVE))
  427.     tmp=tmp->above;
  428.   if(tmp==NULL) {
  429.     insert_ob_in_map(op,op->map);
  430.     return;
  431.   }
  432.   if (QUERY_FLAG(tmp, FLAG_REFL_MISSILE)){
  433.     int number = op->face->number;
  434.     op->direction=absdir(op->direction+4),op->state=0;
  435.     number+=4;
  436.     if(number > op->arch->faces[8])
  437.       number-=8;
  438.     op->face = &new_faces[number];
  439.     insert_ob_in_map(op,op->map);
  440.     return;
  441.   }
  442.   if(attack_ob(tmp,op))
  443.     stop_arrow(op,tmp);
  444.   else
  445.     if(op->direction)
  446.       insert_ob_in_map(op,op->map);
  447.     else
  448.       stop_arrow(op,NULL);
  449. }
  450.  
  451. #if 0
  452. void stop_thrown(object *op,object *tmp) {
  453.   if(wall(op->map,op->x,op->y))
  454.     op->x-=DIRX(op),op->y-=DIRY(op);
  455.   op->direction=0;
  456.   UNSET_FLY(op);
  457.   if(op->type!=BOMB) {
  458.     update_ob_speed(op,0);
  459.     op->speed_left= -2;
  460.   }
  461.   insert_ob_in_map(op,op->map);
  462.   if(tmp!=NULL&&tmp->stats.hp>=0) { /* Hack to get monster on top */
  463.     remove_ob(tmp);
  464.     insert_ob_in_map(tmp,tmp->map);
  465.   }
  466. }
  467. #endif
  468.  
  469. #if 0 /* This routine is buggy, and removed for now */
  470. void move_thrown(object *op) {
  471.   object *tmp;
  472.   int roll;
  473.   char buf[MAX_BUF];
  474.  
  475.   remove_ob(op);
  476.   if(op->thrown--<1) {
  477.     stop_thrown(op,NULL);
  478.     return;
  479.   }
  480.   op->x+=DIRX(op),op->y+=DIRY(op);
  481.   if(out_of_map(op->map,op->x,op->y)) {
  482.     LOG(llevError,"Thrown object out of map.\n");
  483.     stop_thrown(op,NULL);
  484.     remove_ob(op);
  485.     free_object(op);
  486.     return;
  487.   }
  488.   if(wall(op->map,op->x,op->y)) {
  489.     stop_thrown(op,NULL);
  490.     return;
  491.   }
  492.   tmp=get_map_ob(op->map,op->x,op->y);
  493.   while(tmp!=NULL&&!QUERY_FLAG(tmp, FLAG_ALIVE))
  494.     tmp=tmp->above;
  495.   if(tmp==NULL) {
  496.     insert_ob_in_map(op,op->map);
  497.     return;
  498.   }
  499.   roll=RANDOM()%20+1;
  500.   if(roll==20||tmp->stats.ac>=op->thrownthaco-roll) {
  501.     sprintf(buf,"%s hits you with %s.",op->owner->name,op->name);
  502.     new_draw_info(NDI_UNIQUE, 0,tmp,buf);
  503.     new_draw_info_format(NDI_ALL, 10, NULL,
  504.     "%s hits %s with %s.",op->owner->name,tmp->name,op->name);
  505.     hit_player(tmp,RANDOM()%(op->weight>50000?11:op->weight/5000+1),op->owner,
  506.                AT_PHYSICAL);
  507.     stop_thrown(op,tmp);
  508.     return;
  509.   } else
  510.   if(op->thrownthaco-roll<5) {
  511.     new_draw_info_format(NDI_ALL, 10, NULL,
  512.     "%s's %s hits %s's armour.",op->owner->name,op->name,tmp->name);
  513.     stop_thrown(op,tmp);
  514.     return;
  515.   }
  516.   insert_ob_in_map(op,op->map);
  517. }
  518. #endif
  519.  
  520. /* This routine doesnt seem to work for "inanimate" objects that
  521.  * are being carried, ie a held torch leaps from your hands!. 
  522.  * Modified this routine to allow held objects. b.t. */
  523.  
  524. void change_object(object *op) { /* Doesn`t handle linked objs yet */
  525.   object *tmp,*env;
  526.   int i,j;
  527.   if(op->other_arch==NULL) {
  528.     LOG(llevError,"Change object (%s) without other_arch error.\n", op->name);
  529.     return;
  530.   }
  531.   env=op->env;
  532.   remove_ob(op);
  533.   for(i=0;i<NROFNEWOBJS(op);i++) {
  534.     tmp=arch_to_object(op->other_arch);
  535.     tmp->stats.hp=op->stats.hp; /* The only variable it keeps. */
  536.     if(env) {
  537.         tmp->x=env->x,tmp->y=env->y;
  538.     insert_ob_in_ob(tmp,env);
  539.     } else {
  540.         j=find_first_free_spot(tmp->arch,op->map,op->x,op->y);
  541.         tmp->x=op->x+freearr_x[j],tmp->y=op->y+freearr_y[j];
  542.         insert_ob_in_map(tmp,op->map);
  543.     }
  544.   }
  545.   free_object(op);
  546. }
  547.  
  548. void move_teleporter(object *op) {
  549.   if(op->above!=NULL) {
  550.     if(EXIT_PATH(op)) {
  551.       if(op->above->type==PLAYER)
  552.         enter_exit(op->above,op);
  553.       else
  554.         return;
  555.     }
  556.     else if(EXIT_X(op)||EXIT_Y(op))
  557.     {
  558.       if (out_of_map(op->map, EXIT_X(op), EXIT_Y(op)))
  559.       {
  560.         LOG(llevError, "Removed illegal teleporter.\n");
  561.         remove_ob(op);
  562.         free_object(op);
  563.         return;
  564.       }
  565.       transfer_ob(op->above,EXIT_X(op),EXIT_Y(op));
  566.     } else
  567.       teleport(op,TELEPORTER);
  568.   }
  569. }
  570.  
  571. /*  peterm:  firewalls generalized to be able to shoot any type
  572.     of spell at all.  the stats.dam field of a firewall object
  573.     contains it's spelltype.      The direction of the wall is stored
  574.     in op->stats.sp.  maxsp also has some meaning, i'm not sure what.
  575.     walls can have hp, so they can be torn down. */
  576. void move_firewall(object *op) {
  577.   cast_spell(op,op,op->stats.sp?op->stats.sp:(RANDOM()%8)+1,op->stats.dam,
  578.     1,spellNormal,NULL);
  579. }
  580.  
  581. void move_firechest(object *op) {
  582.   fire_a_ball(op,(RANDOM()%8)+1,7);
  583. }
  584.  
  585.  
  586. /*  move_player_mover:  this function takes a "player mover" as an
  587. argument, and performs the function of a player mover, which is:
  588.  
  589.   a player mover finds any players that are sitting on it.  It
  590. moves them in the op->stats.sp direction.  speed is how often it'll move.
  591. If attacktype is nonzero it will paralyze the player.  If lifesave is set,
  592. it'll dissapear after hp+1 moves.  If hp is set and attacktype is set,
  593. it'll paralyze the victim for hp*his speed/op->speed
  594.  
  595. */
  596. void move_player_mover(object *op) {
  597.   object *victim, *nextmover;
  598.   for(victim=get_map_ob(op->map,op->x,op->y); victim !=NULL; victim=victim->above)
  599.     if(QUERY_FLAG(victim, FLAG_ALIVE)&& (!(QUERY_FLAG(victim,FLAG_FLYING))||op->stats.maxhp))
  600.       {
  601.       if(QUERY_FLAG(op,FLAG_LIFESAVE)&&op->stats.hp--<0) {
  602.     remove_ob(op);
  603.     free_object(op);
  604.     return;
  605.       }
  606.  
  607.       for(nextmover=get_map_ob(op->map,op->x+freearr_x[op->stats.sp],op->y+freearr_y[op->stats.sp]); nextmover !=NULL; nextmover=nextmover->above) {
  608.     if(nextmover->type == PLAYERMOVER) 
  609.        { nextmover->speed_left=-.99;}
  610.     if(QUERY_FLAG(nextmover,FLAG_ALIVE)) {
  611.       op->speed_left=-1.1;  /* wait until the next thing gets out of the way */
  612.     }
  613.       }
  614.  
  615.       if(victim->type==PLAYER)  /*  only level >=1 movers move people */
  616.          { if(op->level) move_player(victim, op->stats.sp?op->stats.sp:(RANDOM()%8)+1);
  617.         else return;
  618.      }
  619.       else move_object(victim,op->stats.sp?op->stats.sp:(RANDOM()%8)+1);
  620.  
  621.       if(!op->stats.maxsp&&op->attacktype) op->stats.maxsp=2.0;
  622.  
  623.       if(op->attacktype)  /* flag to paralyze the player */
  624.         victim->speed_left= -FABS(op->stats.maxsp*victim->speed/op->speed);
  625.       }
  626.  
  627. }
  628.  
  629. /*  move_creator (by peterm) 
  630.   it has the creator object create it's other_arch right on top of it.
  631.   connected:  what will trigger it
  632.   hp:  how many times it may create before stopping
  633.   lifesave:  if set, it'll never disappear but will go on creating
  634.     everytime it's triggered
  635.   other_arch:  the object to create
  636. */
  637.  
  638. void move_creator(object *op) {
  639.   object *tmp;
  640.   op->stats.hp--;
  641.   if(op->stats.hp < 0 && !QUERY_FLAG(op,FLAG_LIFESAVE)) 
  642.     { op->stats.hp=-1;return;}
  643.   tmp=arch_to_object(op->other_arch);
  644.   tmp->x=op->x;tmp->y=op->y;tmp->map=op->map;tmp->level=op->level;
  645.   insert_ob_in_map(tmp,op->map);
  646. }
  647.  
  648.   
  649.  
  650. int process_object(object *op) {
  651.  
  652.   if(QUERY_FLAG(op, FLAG_MONSTER))
  653.     if(move_monster(op) || QUERY_FLAG(op, FLAG_FREED)) 
  654.       return 1;
  655.   if(QUERY_FLAG(op, FLAG_ANIMATE) && op->anim_speed==0) {
  656.     animate_object(op);
  657.     if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE))
  658.       make_sure_seen(op);
  659.   }
  660.   if(QUERY_FLAG(op, FLAG_CHANGING)&&!op->state) {
  661.     change_object(op);
  662.     return 1;
  663.   }
  664.   if(QUERY_FLAG(op, FLAG_GENERATOR))
  665.     generate_monster(op);
  666.   if(QUERY_FLAG(op, FLAG_IS_USED_UP)&&--op->stats.food<=0) {
  667.     if(QUERY_FLAG(op, FLAG_APPLIED))
  668.       remove_force(op);
  669.     else {
  670.       remove_ob(op);
  671.       if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE))
  672.         make_sure_not_seen(op);
  673.       free_object(op);
  674.     }
  675.     return 1;
  676.   }
  677.   switch(op->type) {
  678.   case ROD:
  679.   case HORN:
  680.     regenerate_rod(op);
  681.     return 1;
  682.   case FORCE:
  683.     remove_force(op);
  684.     return 1;
  685.   case BLINDNESS:
  686.     remove_blindness(op);
  687.     return 0;
  688.   case CONFUSION:
  689.     remove_confusion(op);
  690.     return 0;
  691.   case POISONING:
  692.     poison_more(op);
  693.     return 0;
  694.   case WORD_OF_RECALL:
  695.     execute_wor(op);
  696.     return 0;
  697.   case BULLET:
  698.     move_fired_arch(op);
  699.     return 0;
  700.   case MMISSILE:
  701.     move_missile(op);
  702.     return 0;
  703.   case ARROW:
  704.     move_arrow(op);
  705.     return 0;
  706.   case FBULLET:
  707.     move_fired_arch(op);
  708.     return 0;
  709.   case FBALL:
  710.   case POISONCLOUD:
  711.     explosion(op);
  712.     return 0;
  713.   case LIGHTNING: /* It now moves twice as fast */
  714.     move_bolt(op);
  715.     return 0;
  716.   case CONE:
  717.     move_cone(op);
  718.     return 0;
  719.   case DOOR:
  720.     remove_door(op);
  721.     return 0;
  722.   case LOCKED_DOOR:
  723.     remove_door2(op);
  724.     return 0;
  725.   case TELEPORTER:
  726.     move_teleporter(op);
  727.     return 0;
  728.   case BOMB:
  729.     animate_bomb(op);
  730.     return 0;
  731.   case GOLEM:
  732.     move_golem(op);
  733.     return 0;
  734.   case EARTHWALL:
  735.     hit_player(op, 2, op, AT_PHYSICAL);
  736.     return 0;
  737.   case FIREWALL:
  738.     move_firewall(op);
  739.     if (op->stats.maxsp)
  740.       animate_turning(op);
  741.     return 0;
  742.   case FIRECHEST:
  743.     move_firechest(op);
  744.     return 0;
  745.   case MOOD_FLOOR:
  746.     do_mood_floor(op, op);
  747.     return 0;
  748.   case GATE:
  749.     move_gate(op);
  750.     return 0;
  751.   case TIMED_GATE:
  752.     move_timed_gate(op);
  753.     return 0;
  754.   case TRIGGER:
  755.   case TRIGGER_BUTTON:
  756.   case TRIGGER_PEDESTAL:
  757.   case TRIGGER_ALTAR:
  758.     animate_trigger(op);
  759.     return 0;
  760.   case DIRECTOR:
  761.     if (op->stats.maxsp)
  762.       animate_turning(op);
  763.     return 0;
  764.   case HOLE:
  765.     move_hole(op);
  766.     return 0;
  767.   case DEEP_SWAMP:
  768.     deep_swamp(op, 0);
  769.     return 0;
  770.   case CANCELLATION:
  771.     move_cancellation(op);
  772.     return 0;
  773.   case BALL_LIGHTNING:
  774.     move_ball_lightning(op);
  775.     return 0;
  776.   case SWARM_SPELL:
  777.     move_swarm_spell(op);
  778.     return 0;
  779.   case RUNE:
  780.     move_rune(op);
  781.     return 0;
  782.   case PLAYERMOVER:
  783.     move_player_mover(op);
  784.     return 0;
  785.   }
  786.  
  787.   return 0;
  788. }
  789.  
  790.